package com.health.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.health.common.PageBean;
import com.health.common.QueryParam;
import com.health.mapper.SetmealMapper;
import com.health.pojo.CheckGroup;
import com.health.pojo.CheckItem;
import com.health.pojo.Setmeal;
import com.health.pojo.SetmealCheckGroup;
import com.health.service.*;
import com.health.vo.CheckGroupVO;
import com.health.vo.SetmealDetailVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {

    private final SetmealCheckGroupService setmealCheckGroupService;
    private final CheckGroupService checkGroupService;
    private final CheckGroupCheckItemService checkGroupCheckItemService;
    private final CheckItemService checkItemService;


    /**
     * 分页条件查询
     *
     * @param param
     * @return
     */
    @Override
    public PageBean pageQuery(QueryParam param) {
        Page<Setmeal> page = new Page<>(param.getCurrentPage(), param.getPageSize());
        this.query().like(param.getQueryString() != null, "name", param.getQueryString()).or().like(param.getQueryString() != null, "code", param.getQueryString()).or().like(param.getQueryString() != null, "help_code", param.getQueryString()).page(page);

        return new PageBean(page.getRecords(), page.getTotal());
    }

    /**
     * 保存套餐及检查组关系
     *
     * @param setmeal
     * @param checkGroupIds
     */
    @Override
    @Transactional //事务管理
    public void addSetmeal(Setmeal setmeal, Integer[] checkGroupIds) {
        //1. 保存套餐基本信息
        this.save(setmeal);
        //2. 保存套餐检查组关系   List<Integer>     List<SetmealCheckGroup>
        List<SetmealCheckGroup> list = Arrays.stream(checkGroupIds)
                .map(checkGroupId -> new SetmealCheckGroup(null, setmeal.getId(), checkGroupId))
                .collect(Collectors.toList());
        //批量保存套餐检查组关系
        setmealCheckGroupService.saveBatch(list);
    }

    /**
     * 根据id查询套餐对应的检查组列表
     *
     * @param id
     * @return
     */
    @Override
    public List<CheckGroup> getCheckGroupsById(Integer id) {
        //1. 向查询套餐检查组中间表，获取套餐对应的检查组关系
        //select * from t_setmeal_checkgroup where setmeal_id = ?
        List<SetmealCheckGroup> setmealCheckGroups = setmealCheckGroupService.query()
                .eq("setmeal_id", id)
                .list();
        //List<SetmealCheckGroup>   ->   List<Integer>
        List<Integer> checkGroupIds = setmealCheckGroups.stream()
                .map(setmealCheckGroup -> setmealCheckGroup.getCheckgroupId())
                .collect(Collectors.toList());

        //2. 再根据检查组ids查询检查组信息
        return checkGroupService.query().in("id", checkGroupIds).list();
    }

    /**
     * 修改套餐及检查组关系
     *
     * @param setmeal
     * @param checkGroupIds
     */
    @Override
    @Transactional
    public void updateSetmeal(Setmeal setmeal, Integer[] checkGroupIds) {
        //1. 修改套餐基本信息
        this.updateById(setmeal);
        //2. 删除套餐对应的检查组关系
        setmealCheckGroupService.update()
                .eq("setmeal_id", setmeal.getId())
                .remove();
        //3. 添加套餐对应的检查组关系
        //List<Integer>  ->  List<SetmealCheckGroup>
        List<SetmealCheckGroup> setmealCheckGroupList = Arrays.stream(checkGroupIds)
                .map(checkGroupId -> new SetmealCheckGroup(null, setmeal.getId(), checkGroupId))
                .collect(Collectors.toList());
        //批量保存套餐检查组关系
        setmealCheckGroupService.saveBatch(setmealCheckGroupList);
    }

    /**
     * 删除套餐以及检查组关系
     *
     * @param id
     */
    @Override
    @Transactional
    public void deleteSetmeal(Integer id) {
        //1. 删除套餐信息
        this.removeById(id);
        //2. 删除套餐对应检查组关系
        setmealCheckGroupService.update()
                .eq("setmeal_id", id)
                .remove();
    }

    /**
     * 获取套餐详情信息
     *
     * @param id
     * @return
     */
    @Override
    public SetmealDetailVO getSetmealDetailById(Integer id) {
        //1. 查询套餐基本信息
        Setmeal setmeal = this.getById(id);

        //2. 查询套餐对应的检查组信息
        List<SetmealCheckGroup> setmealCheckGroups = setmealCheckGroupService.query().eq("setmeal_id", id).list();
        // List<SetmealCheckGroup>   --->   List<CheckGroup>
        List<CheckGroup> checkGroups = setmealCheckGroups.stream()
                .map(setmealCheckGroup -> checkGroupService.getById(setmealCheckGroup.getCheckgroupId()))
                .collect(Collectors.toList());

        // List<CheckGroup>   --->   List<CheckGroupVO>
        List<CheckGroupVO> checkGroupVOS = checkGroups.stream().map(checkGroup -> {
            CheckGroupVO checkGroupVO = new CheckGroupVO();
            //将checkGroup中的数据拷贝到CheckGroupVO中
            BeanUtils.copyProperties(checkGroup, checkGroupVO);
            //根据检查组查询对应的检查项列表
            List<CheckItem> checkItems = checkGroupCheckItemService.query()
                    .eq("checkgroup_id", checkGroup.getId())
                    .list()
                    .stream()
                    .map(checkGroupCheckItem -> checkItemService.getById(checkGroupCheckItem.getCheckitemId()))
                    .collect(Collectors.toList());
            // 设置检查组的检查项列表
            checkGroupVO.setCheckItemList(checkItems);
            // 返回已经设置好检查项的检查组视图对象
            return checkGroupVO;
        }).collect(Collectors.toList());


        // 创建一个SetmealDetailVO对象，用于封装套餐详情信息
        SetmealDetailVO setmealDetailVO = new SetmealDetailVO();
        // 将setmeal对象的属性值复制到setmealDetailVO对象中，实现对象间的属性转移
        BeanUtils.copyProperties(setmeal, setmealDetailVO);
        // 设置套餐详情中的检查组信息，checkGroupVOS为检查组的集合
        setmealDetailVO.setCheckGroups(checkGroupVOS);
        return setmealDetailVO;
    }

    /**
     * 套餐统计
     *
     * @return
     */
    @Override
    public List<Map<String, Object>> getSetmealReportData() {
        return this.getBaseMapper().getSetmealReportData();
    }

}
